package util;


import org.smartboot.socket.util.StringUtils;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.*;

public class ByteExtUtil {
    public static byte[] getBytes(short data) {
        byte[] bytes = new byte[2];
        bytes[1] = (byte) (data & 0xff);
        bytes[0] = (byte) ((data & 0xff00) >> 8);
        return bytes;
    }

    public static byte[] getBytes(char data) {
        byte[] bytes = new byte[2];
        bytes[1] = (byte) (data);
        bytes[0] = (byte) (data >> 8);
        return bytes;
    }

    public static byte[] getBytes(int data) {
        byte[] bytes = new byte[4];
        bytes[3] = (byte) (data & 0xff);
        bytes[2] = (byte) ((data & 0xff00) >> 8);
        bytes[1] = (byte) ((data & 0xff0000) >> 16);
        bytes[0] = (byte) ((data & 0xff000000) >> 24);
        return bytes;
    }

    public static byte[] getBytes(long data) {
        byte[] bytes = new byte[8];
        bytes[7] = (byte) (data & 0xff);
        bytes[6] = (byte) ((data >> 8) & 0xff);
        bytes[5] = (byte) ((data >> 16) & 0xff);
        bytes[4] = (byte) ((data >> 24) & 0xff);
        bytes[3] = (byte) ((data >> 32) & 0xff);
        bytes[2] = (byte) ((data >> 40) & 0xff);
        bytes[1] = (byte) ((data >> 48) & 0xff);
        bytes[0] = (byte) ((data >> 56) & 0xff);
        return bytes;
    }

    public static byte[] getBytes(float data) {
        int intBits = Float.floatToIntBits(data);
        return getBytes(intBits);
    }

    public static byte[] getBytes(double data) {
        long intBits = Double.doubleToLongBits(data);
        return getBytes(intBits);
    }

    public static byte[] getBytes(String data, String charsetName) {
        Charset charset = Charset.forName(charsetName);
        return data.getBytes(charset);
    }

    public static byte[] getBytes(String data) {
        return getBytes(data, "GBK");
    }

    public static short getShort(byte[] bytes) {
        return (short) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
    }

    public static char getChar(byte[] bytes) {
        return (char) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
    }

    public static int getInt(byte[] bytes) {
        return (0xff & bytes[3]) | (0xff00 & (bytes[2] << 8))
                | (0xff0000 & (bytes[1] << 16))
                | (0xff000000 & (bytes[0] << 24));
    }

    public static long getLong(byte[] bytes) {
        return (0xffL & (long) bytes[7]) | (0xff00L & ((long) bytes[6] << 8))
                | (0xff0000L & ((long) bytes[5] << 16))
                | (0xff000000L & ((long) bytes[4] << 24))
                | (0xff00000000L & ((long) bytes[3] << 32))
                | (0xff0000000000L & ((long) bytes[2] << 40))
                | (0xff000000000000L & ((long) bytes[1] << 48))
                | (0xff00000000000000L & ((long) bytes[0] << 56));
    }

    public static float getFloat(byte[] bytes) {
        return Float.intBitsToFloat(getInt(bytes));
    }

    public static double getDouble(byte[] bytes) {
        long l = getLong(bytes);
        return Double.longBitsToDouble(l);
    }

    public static String getString(byte[] bytes, String charsetName) {
        return new String(bytes, Charset.forName(charsetName));
    }

    public static String getString(byte[] bytes, int from, int to, String charsetName) {
        byte[] data = Arrays.copyOfRange(bytes, from, to);
        return new String(data, Charset.forName(charsetName));
    }

    public static String getString(byte[] bytes) {
        return getString(bytes, "GBK");
    }

    public static String getString(byte[] bytes, int from, int to) {
        return getString(bytes, from, to, "GBK");
    }

    public static String getString(int[] bytes, int from, int to) {
        byte[] bytes1 = new byte[bytes.length];
        for (int i = 0; i <= bytes.length - 1; i++) {
            bytes1[i] = (byte) bytes[i];
        }

        return getString(bytes1, from, to);
    }

    public static Integer[] floatToModbus(float value) {
        try {
            //String source = floatToIEEE754(value);
            //Integer[] results = changeHex(source);
            int intBits = Float.floatToIntBits(value);
            String source = Integer.toBinaryString(intBits);
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i < 32 - source.length(); i++) {
                buffer.append("0");
            }
            StringBuffer change = new StringBuffer();
            change.append(buffer.toString());
            change.append(source);
            Integer[] results = changeHex(change.toString());
            return results;
        } catch (Exception ex) {
            return null;
        }
    }

    public static Integer[] integerToModbus(int value) {
        try {
            String source = Integer.toBinaryString(value);
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i < 32 - source.length(); i++) {
                buffer.append("0");
            }
            StringBuffer change = new StringBuffer();
            change.append(buffer.toString());
            change.append(source);
            Integer[] results = changeHex(change.toString());
            return results;
        } catch (Exception ex) {
            return null;
        }
    }

    @SuppressWarnings("unused")
    private static String floatToIEEE754(float value) {
        //符号位
        String sflag = value > 0 ? "0" : "1";
        //整数部分
        int fz = (int) Math.floor(value);
        //整数部分二进制
        String fzb = Integer.toBinaryString(fz);
        //小数部分，格式： 0.02
        String valueStr = String.valueOf(value);
        String fxStr = "0" + valueStr.substring(valueStr.indexOf("."));
        float fx = Float.parseFloat(fxStr);
        //小数部分二进制
        String fxb = toBin(fx);
        //指数位
        String e = Integer.toBinaryString(127 + fzb.length() - 1);
        //尾数位
        String m = fzb.substring(1) + fxb;
        String result = sflag + e + m;
        while (result.length() < 32) {
            result += "0";
        }
        if (result.length() > 32) {
            result = result.substring(0, 32);
        }
        return result;
    }

    private static String toBin(float f) {
        List<Integer> list = new ArrayList<Integer>();
        Set<Float> set = new HashSet<Float>();
        int MAX = 24; // 最多8位
        int bits = 0;
        while (true) {
            f = calc(f, set, list);
            bits++;
            if (f == -1 || bits >= MAX)
                break;
        }
        String result = "";
        for (Integer i : list) {
            result += i;
        }
        return result;
    }

    private static float calc(float f, Set<Float> set, List<Integer> list) {
        if (f == 0 || set.contains(f))
            return -1;
        float t = f * 2;
        if (t >= 1) {
            list.add(1);
            return t - 1;
        } else {
            list.add(0);
            return t;
        }
    }

    private static Integer[] changeHex(String sources) {
        if (sources != null && sources != "") {
            StringBuffer buffer = new StringBuffer();
            int i = 0;
            Integer[] result = new Integer[2];
            while (true) {
                if (i * 4 < sources.length()) {
                    String sub = sources.substring(i * 4, (i + 1) * 4);
                    buffer.append(Integer.toString(Integer.parseInt(sub, 2), 16));
                    i++;
                } else {
                    break;
                }
            }
            result[1] = Integer.valueOf(buffer.toString().substring(0, 4), 16);
            result[0] = Integer.valueOf(buffer.toString().substring(4), 16);
            return result;
        } else {
            return null;
        }
    }

    /**
     * byte[]字节数组转hex16进制字符串
     * @param bytes
     * @return
     */
    public static String bytesToHex(byte[] bytes) {
        String hex = new BigInteger(1, bytes).toString(16);
        return hex;
    }
    /**
     * 十六进制字符转中文字符
     *
     * @param s
     * @return
     */
    public static String hexToStringGBK(String s) {
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
                return "";
            }
        }
        try {
            s = new String(baKeyword, "GBK");// UTF-16le:Not
        } catch (Exception e1) {
            e1.printStackTrace();
            return "";
        }
        return s;
    }

    /**
     * 16进制字符串转化为字节数组
     *
     * @param hexString
     * @return byte[]
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toLowerCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    /**
     * 转化字符串为十六进制编码
     */
    public static String toHexString(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return str;
    }

    /**
     * 十进制版本号转换成十六进制表示
     */
    public static String verToHexString(String ver) {
        if (ver != null && ver != "") {
            String[] verarray = ver.split("\\.");
            if (verarray.length == 2) {
                String verresult = Integer.toHexString(Integer.parseInt(verarray[0])) + Integer.toHexString(Integer.parseInt(verarray[1]));
                return verresult;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * Convert char to byte
     *
     * @param c char
     * @return byte
     */
    private static byte charToByte(char c) {
        return (byte) "0123456789abcdef".indexOf(c);
    }

    public static int byteToInt(byte b) {
        //Java 总是把 byte 当做有符处理；我们可以通过将其和 0xFF 进行二进制与得到它的无符值
        return b & 0xFF;
    }

    /**
     * 十进制版本号转换成二进制表示并补齐长度
     */
    public static String toBinaryString(int decNum, int digit) {
        String binStr = "";
        for (int i = digit - 1; i >= 0; i--) {
            binStr += (decNum >> i) & 1;
        }
        return binStr;
    }

    /**
     * 十进制版本号转换成二进制表示补齐长度，并且取反。
     */
    public static String toBinaryInvertString(int decNum, int digit) {
        String binStr = "";
        for (int i = digit - 1; i >= 0; i--) {
            binStr += ~(decNum >> i) & 1;
        }
        return binStr;
    }


    public static final int UNICODE_LEN = 2;


    /**
     * int转换为小端byte[]（高位放在高地址中）
     *
     * @param iValue
     * @return
     */
    public static byte[] Int2Bytes_LE(int iValue) {
        byte[] rst = new byte[4];
        // 先写int的最后一个字节
        rst[0] = (byte) (iValue & 0xFF);
        // int 倒数第二个字节
        rst[1] = (byte) ((iValue & 0xFF00) >> 8);
        // int 倒数第三个字节
        rst[2] = (byte) ((iValue & 0xFF0000) >> 16);
        // int 第一个字节
        rst[3] = (byte) ((iValue & 0xFF000000) >> 24);
        return rst;
    }


    /**
     * 转换String为byte[]
     *
     * @param str
     * @return
     */
    public static byte[] String2Bytes_LE(String str) {
        if (str == null) {
            return null;
        }
        char[] chars = str.toCharArray();

        byte[] rst = Chars2Bytes_LE(chars);

        return rst;
    }


    /**
     * 转换字符数组为定长byte[]
     *
     * @param chars 字符数组
     * @return 若指定的定长不足返回null, 否则返回byte数组
     */
    public static byte[] Chars2Bytes_LE(char[] chars) {
        if (chars == null)
            return null;

        int iCharCount = chars.length;
        byte[] rst = new byte[iCharCount * UNICODE_LEN];
        int i = 0;
        for (i = 0; i < iCharCount; i++) {
            rst[i * 2] = (byte) (chars[i] & 0xFF);
            rst[i * 2 + 1] = (byte) ((chars[i] & 0xFF00) >> 8);
        }

        return rst;
    }


    /**
     * 转换byte数组为int（小端）
     *
     * @return
     * @note 数组长度至少为4，按小端方式转换,即传入的bytes是小端的，按这个规律组织成int
     */
    public static int Bytes2Int_LE(byte[] bytes) {
        if (bytes.length < 4)
            return -1;
        int iRst = (bytes[0] & 0xFF);
        iRst |= (bytes[1] & 0xFF) << 8;
        iRst |= (bytes[2] & 0xFF) << 16;
        iRst |= (bytes[3] & 0xFF) << 24;

        return iRst;
    }


    /**
     * 转换byte数组为int（大端）
     *
     * @return
     * @note 数组长度至少为4，按小端方式转换，即传入的bytes是大端的，按这个规律组织成int
     */
    public static int Bytes2Int_BE(byte[] bytes) {
        if (bytes.length < 4)
            return -1;
        int iRst = (bytes[0] << 24) & 0xFF;
        iRst |= (bytes[1] << 16) & 0xFF;
        iRst |= (bytes[2] << 8) & 0xFF;
        iRst |= bytes[3] & 0xFF;

        return iRst;
    }


    /**
     * 转换byte数组为Char（小端）
     *
     * @return
     * @note 数组长度至少为2，按小端方式转换
     */
    public static char Bytes2Char_LE(byte[] bytes) {
        if (bytes.length < 2)
            return (char) -1;
        int iRst = (bytes[0] & 0xFF);
        iRst |= (bytes[1] & 0xFF) << 8;

        return (char) iRst;
    }


    /**
     * 转换byte数组为char（大端）
     *
     * @return
     * @note 数组长度至少为2，按小端方式转换
     */
    public static char Bytes2Char_BE(byte[] bytes) {
        if (bytes.length < 2)
            return (char) -1;
        int iRst = (bytes[0] << 8) & 0xFF;
        iRst |= bytes[1] & 0xFF;

        return (char) iRst;
    }

    /**
     * 日期+时间转成bytes
     *
     * @return
     */
    public static byte[] Date2HexBytes() {
        byte[] bytes = new byte[6];
//    	String formatDateTime1 = DateUtils.formatDateTime1(new Date());
//		String[] split = formatDateTime1.split(" ");
//		String[] ymd = split[0].split("-");
//		String[] hms = split[1].split(":");
        //日期
//		bytes[0] = (byte) Integer.valueOf(ymd[0]).intValue();
//		bytes[1] = (byte) Integer.valueOf(ymd[1]).intValue();
//		bytes[2] = (byte) Integer.valueOf(ymd[2]).intValue();

        //时间
//		bytes[3] = (byte) Integer.valueOf(hms[0]).intValue();
//		bytes[4] = (byte) Integer.valueOf(hms[1]).intValue();
//		bytes[5] = (byte) Integer.valueOf(hms[2]).intValue();
        return bytes;
    }


    public static void main(String[] args) {
        float a = 8.5f;
        byte[] bytes = getBytes(a);
        System.out.println(bytes);
        System.out.println(getString(bytes));

        float b = 123.45f;
        int intBits = Float.floatToIntBits(b);
        System.out.println(Integer.toBinaryString(intBits));

        System.out.println("####");
        b = 8.5f;
        intBits = Float.floatToIntBits(b);
        System.out.println(Integer.toBinaryString(intBits));
        short mm = 23;
        System.out.println(Integer.toBinaryString(mm));
        System.out.println(getShort(getBytes(mm)));


        System.out.println("16进制::" + Integer.parseInt("0F", 16));


        short s = 122;
        int i = 122;
        long l = 1222222;

        char c = 'a';

        float f = 122.22f;
        double d = 122.22;

        String string = "";
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(c);
        System.out.println(f);
        System.out.println(d);
        System.out.println(string);

        System.out.println("**************");

        System.out.println(getShort(getBytes(s)));
        System.out.println(getInt(getBytes(i)));
        System.out.println(getLong(getBytes(l)));
        System.out.println(getChar(getBytes(c)));
        System.out.println(getFloat(getBytes(f)));
        System.out.println(getDouble(getBytes(d)));
        System.out.println(getString(getBytes(string)));
    }
}
